const axios = require('axios');
const ora = require('ora');
const Inquirer = require('inquirer');
const path = require('path');
const fs = require('fs');
const { promisify } = require('util');
const config = require('./config');
const repoUrl = config('getVal', 'repo'); //获取到config参数的repoUrl例如：repo=gu-cli 再将此参数全替换为写死的zhu-cli

const Metalsmith = require('metalsmith');// 遍历文件夹看需不需要渲染
// 统一所有模板引擎
let { render } = require('consolidate').ejs;

render = promisify(render);
let downloadGitRepo = require('download-git-repo');
// 可以把异步的api转换成promise
downloadGitRepo = promisify(downloadGitRepo);
let ncp = require('ncp');

ncp = promisify(ncp);
const { downloadDirectory } = require('./constants');
// create的所有逻辑
// create的功能是创建项目 拉取自己的所有项目列出来 让用户选 安装哪个项目
// 选完后再显示所有的版本号

// https://api.github.com/orgs/zhu-cli/repos获取组织下的仓库
// 可能还需要用户配置一些数据来结合渲染我的项目

// 获取项目列表
const fetchRepoList = async () => {
  const { data } = await axios.get('https://api.github.com/orgs/zhu-cli/repos');
  return data;
};

// 获取tag列表
const fetchTagList = async (repo) => {
  const { data } = await axios.get(`https://api.github.com/repos/zhu-cli/${repo}/tags`);
  return data;
};

const download = async (repo, tag) => {
  let api = `gu-cli/${repo}`;
  if (tag) {
    api += `#${tag}`;
  }
  const dest = `${downloadDirectory}/${repo}`;
  await downloadGitRepo(api, dest);
  return dest;// 下载的最终目录
};

const waitFnLoading = (fn, message) => async (...args) => {
  const spinner = ora(message);
  spinner.start();
  const result = await fn(...args);
  spinner.succeed();
  return result;
};

module.exports = async (projectName) => {
  let repos = await waitFnLoading(fetchRepoList, 'fetching template...')();
  repos = repos.map((repo) => repo.name);
  // 选择模板 inquirer & loading状态 ora
  const { repo } = await Inquirer.prompt({
    name: 'repo', // 获取选择后的结果
    type: 'list',
    message: 'please choose a template to create project',
    choices: repos,
  });
  // 通过选择的项目 拉取对应的版本
  // 获取对应的版本号：https://api.github.com/repos/zhu-cli/vue-template/tags
  let tags = await waitFnLoading(fetchTagList, 'fetching tags ...')(repo);
  tags = tags.map((item) => item.name);
  const { tag } = await Inquirer.prompt({
    name: 'tag', // 获取选择后的结果
    type: 'list',
    message: 'please choose a tag to create project',
    choices: tags,
  });
  console.log(repo, tag);
  // download-git-repo
  const result = await waitFnLoading(download, 'download template')(repo, tag);
  console.log(result);
  if (!fs.existsSync(path.join(result, 'ask.js'))) {
  // 拿到了下载的目录 直接拷贝当前执行的目录下即可
    await ncp(result, path.resolve(projectName));
  } else {
    // 复杂的模板
  // 把git上项目下载下来，有ask文件就是复杂的模板 metalsmith只要模版引擎都需要
    await new Promise((resolve, reject) => {
      Metalsmith(__dirname)
        .source(result).destination(path.resolve(projectName))
        .use(async (files, metal, done) => {
          const args = require(path.join(result, 'ask.js'));
          const obj = await Inquirer.prompt(args);
          console.log(obj);
          const meta = metal.metadata();
          Object.assign(meta, obj);
          delete files['ask.js'];
          done();
        })
        .use((files, metal, done) => {
          Reflect.ownKeys(files).forEach(async (file) => {
            if (file.includes('js') || file.includes('json')) {
              const content = files[file].contents.toString();
              if (content.includes('<%')) {
                content = await render(content, obj);
                files[file].contents = Buffer.from(content);
              }
            }
          });
          console.log(metal.metadata());
          done();
        })
        .build((err) => {
          if (err) {
            reject();
          } else {
            resolve();
          }
        });
    });
  }
};
